﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml.Linq;
using EzDesk.DevHelper.DbMgr.Views;
using EzDesk.Utility.Log;
using Microsoft.SqlServer.Management.Smo;
using System.Linq;
using System.Data.Linq;
using EzDesk.Core.Data;
using EzDesk.Core.Model;
using EzDesk.Utility.Web.Extensions;
using EzDesk.Utility;

namespace EzDesk.DevHelper.DbMgr.Presenters
{
    public class DataProcessPresenter : DbMgrPresenterBase
    {
        private IDataProcessView _view;
        private Dictionary<Guid, SimpleUser> _allUsersDic = new Dictionary<Guid, SimpleUser>();

        public DataProcessPresenter(DataProcessPanel dataProcessPanel)
        {
            this._view = dataProcessPanel;
            _logView = dataProcessPanel;

            // 缓存所有用户
            using (var db = new EzDeskDatabaseContainer())
            {
                foreach(var entity in db.UserProfileSet)
                {
                    _allUsersDic.Add(entity.Id, entity.ToSimpleUser());
                }
            }
        }

        private string coreDatabaseName = "EzDeskDatabase";

        private string exportAppFunctionXmlFileName = "EzDeskAppFunctions.xml";
        private string exportFeedXmlFileName = "EzDeskFeedTemplates.xml";
        private string exportCoreInfoXmlFileName = "EzDeskCoreInfo.xml";
        private string exportAttendanceLeavesByLawXmlFileName = "EzDeskAttendanceLeavesByLaw.xml";


        private void dropAllDatabases()
        {
            Server srv = new Server(_dataSourceName);
            foreach (var databaseName in _databaseNameList)
            {
                if (srv.Databases.Contains(databaseName))
                {
                    var database = srv.Databases[databaseName];
                    if (database.UserAccess != DatabaseUserAccess.Single)
                    {
                        database.UserAccess = DatabaseUserAccess.Single;
                        database.Alter(TerminationClause.RollbackTransactionsImmediately);
                        database.Refresh();
                    }
                    database.Drop();
                    _view.WriteLine("删除数据库 " + databaseName + "成功");
                }
            }
        }

        protected void importFeedsTemplate(string xmlFileName)
        {
            using (var db = new EzDeskDatabaseContainer(getEntityConnectionString(coreDatabaseName)))
            {

                XElement rootElement = XElement.Load(xmlFileName);
                var feeds = rootElement.Elements();
                foreach (var feed in feeds)
                {
                    Guid id = Guid.Empty;
                    if (feed.Element("id") != null)
                    {
                        id = new Guid(feed.Element("id").Value);
                    }
                    string templateName = null;
                    if (feed.Element("name") != null)
                    {
                        templateName = feed.Element("name").Value;
                    }
                    string title = null;
                    if (feed.Element("title") != null)
                    {
                        title = feed.Element("title").Value;
                    }
                    string body = null;
                    if (feed.Element("body") != null)
                    {
                        body = feed.Element("body").Value;
                    }
                    int type = 0;
                    if (feed.Element("type") != null)
                    {
                        type = Int32.Parse(feed.Element("type").Value);
                    }
                    string templateIcon = "";
                    if (feed.Element("templateIcon") != null)
                    {
                        templateIcon = feed.Element("templateIcon").Value;
                    }

                    var feedTemplateSet = db.FeedTemplateSet.FirstOrDefault(ft => ft.TemplateName == templateName);
                    if(feedTemplateSet!= null)
                    {
                        feedTemplateSet.TemplateName=templateName;
                        feedTemplateSet.Title = title;
                        feedTemplateSet.Body = body;
                        feedTemplateSet.DefaultTypeValue = type;
                        feedTemplateSet.TemplateIconName = templateIcon;
                    }
                    else
                    {
                        db.FeedTemplateSet.AddObject(
                           new FeedTemplate()
                           {
                               TemplateName = templateName,
                               Id = id,
                               Title = title,
                               Body = body,
                               DefaultTypeValue = type,
                               TemplateIconName = templateIcon,
                           }
                           );   
                    }
                }
                db.SaveChanges();
            }
            _view.WriteLine("更新Feed数据完成！");
        }

        protected void importAppFunctions(string xmlFileName)
        {
            using (var db = new EzDeskDatabaseContainer(getEntityConnectionString(coreDatabaseName)))
            {
                db.DeleteTable("AppFunctionSet");
                db.DeleteTable("AppFunctionTypeSet");                

                #region [ AppFunction Types ]

                // 创建 AppFunctions 类型

                Debug.WriteLine("开始创建AppFunctionType");


                XElement typeElement = XElement.Load(xmlFileName);
                var types = typeElement.Element("Types").Elements();
                foreach (var type in types)
                {
                    Guid appFunctionTypeID = Guid.Empty;
                    if (type.Element("AppFunctionTypeId") != null)
                    {
                        appFunctionTypeID = new Guid(type.Element("AppFunctionTypeId").Value);
                    }
                    string typeName = "";
                    if (type.Element("TypeName") != null)
                    {
                        typeName = type.Element("TypeName").Value;
                    }
                    string displayText = "";
                    if (type.Element("DisplayText") != null)
                    {
                        displayText = type.Element("DisplayText").Value;
                    }
                    string iconName = "";
                    if (type.Element("IconName") != null)
                    {
                        iconName = type.Element("IconName").Value;
                    }

                    int privilege = 0;
                    if (type.Element("Privilege") != null)
                    {
                        privilege = Int32.Parse(type.Element("Privilege").Value);
                    }


                    db.AppFunctionTypeSet.AddObject(
                        new AppFunctionType()
                            {
                                Id = appFunctionTypeID,
                                TypeName = typeName,
                                DisplayText = displayText,
                                IconName = iconName,
                                Privilege = privilege

                            }
                        );
                }
                db.SaveChanges();

                Debug.WriteLine("AppFunctionType创建完成");

                #endregion

                #region [ App Functions ]

                Debug.WriteLine("开始创建AppFunctions");
                XElement rootElement = XElement.Load(xmlFileName);
                var functions = rootElement.Element("Functions").Elements();
                foreach (var function in functions)
                {
                    Guid appFunctionId = Guid.Empty;
                    if (function.Element("AppFunctionId") != null)
                    {
                        appFunctionId = new Guid(function.Element("AppFunctionId").Value);
                    }
                    string appName = "";
                    if (function.Element("AppName") != null)
                    {
                        appName = function.Element("AppName").Value;
                    }
                    Guid functionTypeId = Guid.Empty;
                    if (function.Element("FunctionTypeId") != null)
                    {
                        functionTypeId = new Guid(function.Element("FunctionTypeId").Value);
                    }
                    Guid functionCategoryId = Guid.Empty;
                    if (function.Element("FunctionCategoryId") != null)
                    {
                        functionCategoryId = new Guid(function.Element("FunctionCategoryId").Value);
                    }
                    string title = "";
                    if (function.Element("Title") != null)
                    {
                        title = function.Element("Title").Value;
                    }
                    string description = "";
                    if (function.Element("Description") != null)
                    {
                        description = function.Element("Description").Value;
                    }
                    string iconName = "";
                    if (function.Element("IconName") != null)
                    {
                        iconName = function.Element("IconName").Value;
                    }
                    string funcUrl = "";
                    if (function.Element("FuncUrl") != null)
                    {
                        funcUrl = function.Element("FuncUrl").Value;
                    }
                    int privilege = 0;
                    if (function.Element("Privilege") != null)
                    {
                        privilege = Int32.Parse(function.Element("Privilege").Value);
                    }
                    string permissionNeed = null;
                    if (function.Element("PermissionNeed") != null)
                    {
                        permissionNeed = function.Element("PermissionNeed").Value;
                    }
                    string userAgent = "";
                    if (function.Element("UserAgent") != null)
                    {
                        userAgent = function.Element("UserAgent").Value;
                    }

                    db.AppFunctionSet.AddObject(
                        new AppFunction()
                            {
                                Id = appFunctionId,
                                AppName = appName,
                                FunctionTypeId = functionTypeId,
                                FunctionCategoryId = functionCategoryId,
                                Title = title,
                                Description = description,
                                IconName = iconName,
                                FuncUrl = funcUrl,
                                Privilege = privilege,
                                PermissionNeed = permissionNeed,
                                UserAgent = userAgent
                            }
                        );
                }
                db.SaveChanges();

            }
            _view.WriteLine("更新AppFunctions数据完成！");

                #endregion


        }

        private void importCoreInfos(string exportCoreInfoXmlFileName)
        {
            using (var db = new EzDeskDatabaseContainer(getEntityConnectionString(coreDatabaseName)))
            {
                db.DeleteTable("Permission_GroupSet");
                db.DeleteTable("PermissionSet");

                XElement rootEle = XElement.Load(exportCoreInfoXmlFileName);
                
                var permissionGroups = db.GroupSet.Where(p => p.Type == 2);
                foreach (var permissionGroup in permissionGroups)
                {
                    db.GroupSet.DeleteObject(permissionGroup);
                }
                db.SaveChanges();

                List<SimpleUser> allUsers = db.UserProfileSet.ToList().Select(p => p.ToSimpleUser()).ToList();

                // 添加权限组
                var permissionGroupsEle = rootEle.Element("permissionGroups");
                foreach (var permissionGroupEle in permissionGroupsEle.Elements())
                {
                    var groupName = permissionGroupEle.Element("name").Value;
                    var groupDescription = permissionGroupEle.Element("description").Value;
                    string memberstring = "";
                    if (permissionGroupEle.Element("groupUsers").HasElements)
                    {
                        var userIdArray = new List<Guid>();
                        var userNameList = permissionGroupEle.Element("groupUsers").Element("users").Elements().Select(p => p.Value).ToList();
                        memberstring = getMemberstringFromUserNameList(userNameList, allUsers, userIdArray);
                    }
                    else
                    {
                        memberstring = permissionGroupEle.Element("groupUsers").Value;
                    }
                    var theGroup = new Group()
                    {
                        Id = Guid.NewGuid(),
                        Description = groupDescription,
                        Memberstring = memberstring,
                        Type = 2,
                        Name = groupName
                    };
                    db.GroupSet.AddObject(theGroup);
                }
                db.SaveChanges();

                // 添加权限
                var permissionsEle = rootEle.Element("permissions");
                foreach (var permissionEle in permissionsEle.Elements())
                {
                    var permissionName = permissionEle.Element("name").Value;
                    var permissionDescription = permissionEle.Element("description").Value;
                    var defaultDeny = permissionEle.Element("defaultDeny").Value;
                    var permission = new Permission()
                    {
                        Id = Guid.NewGuid(),
                        DefaultDeny = defaultDeny == "true",
                        Description = permissionDescription,
                        Name = permissionName
                    };
                    db.PermissionSet.AddObject(permission);

                    var groupNames = permissionEle.Element("groups").Elements().Select(p => p.Value).ToList();

                    foreach (var groupName in groupNames)
                    {
                        var group = db.GroupSet.FirstOrDefault(p => p.Name == groupName);
                        if (group != null)
                        {
                            var entity = new Permission_Group()
                            {
                                GroupId = group.Id,
                                PermissionId = permission.Id,
                                HasPermission = true,
                            };
                            db.Permission_GroupSet.AddObject(entity);
                        }
                    }
                }

                db.SaveChanges();
            }

            LogEx.TRACE("DataProcess", "导入CoreInfos完成");
            _view.WriteLine("导入CoreInfos完成");
        }

        private string getMemberstringFromUserNameList(List<string> userNameList, List<SimpleUser> allUsers, List<Guid> userIdArray)
        {
            string memberstring;
            foreach (var userName in userNameList)
            {
                var user = allUsers.FirstOrDefault(p => p.UserName.ToLower() == userName.ToLower());
                if (user != null)
                {
                    userIdArray.Add(user.Id);
                }
            }
            memberstring = userIdArray.Join(",");
            return memberstring;
        }


        public void ExporttAppFunctionXml()
        {
            XElement saveXml = new XElement("AppFuntions");

            using (var db = new EzDeskDatabaseContainer(getEntityConnectionString(coreDatabaseName)))
            {
                XElement functionType = new XElement("Types");
                foreach (var entity in db.AppFunctionTypeSet)
                {
                    functionType.Add(
                        new XElement("Type",
                            new XElement("AppFunctionTypeId", entity.Id.ToString()),
                            new XElement("TypeName", entity.TypeName),
                            new XElement("DisplayText", entity.DisplayText),
                            new XElement("IconName", entity.IconName),
                            new XElement("Privilege", entity.Privilege.ToString())
                    ));
                }

                XElement function = new XElement("Functions");
                foreach (var entity in db.AppFunctionSet)
                {
                    function.Add(new XElement("Function",
                        new XElement("AppFunctionId", entity.Id.ToString()),
                            new XElement("AppName", entity.AppName),
                            new XElement("FunctionTypeId", entity.FunctionTypeId.ToString()),
                            new XElement("FunctionCategoryId", entity.FunctionCategoryId.ToString()),
                            new XElement("Title", entity.Title),
                            new XElement("Description", entity.Description),
                            new XElement("IconName", entity.IconName),
                            new XElement("FuncUrl", entity.FuncUrl),
                            new XElement("Privilege", entity.Privilege.ToString()),
                            new XElement("PermissionNeed", entity.PermissionNeed),
                            new XElement("UserAgent", entity.UserAgent)
                        )
                        );
                }

                saveXml.Add(functionType);
                saveXml.Add(function);
            }

            saveXml.Save(exportAppFunctionXmlFileName);

            _view.WriteLine("生成 " + exportAppFunctionXmlFileName + " 成功");
            try
            {
                // 如果在开发环境下，尝试更新用于开发的文件
                CopyFileToDevEnv(exportAppFunctionXmlFileName);
            }
            catch (Exception ex)
            {
                _view.WriteLine("复制生成的文件到开发环境出错，可能是没有CheckOut " + exportAppFunctionXmlFileName + "  " + ex.Message);
            }

        }

        public void ExportFeedTemplateXml()
        {
            LogEx.TRACE("MainForm - Presenter", "开始将当前数据库内容导出到XML");

            var root = new XElement("FeedTemplates");

            using (var db = new EzDeskDatabaseContainer(getEntityConnectionString(coreDatabaseName)))
            {
                foreach (var entity in db.FeedTemplateSet)
                {
                    XElement feedTempalteEle = new XElement("feedTemplate");
                    feedTempalteEle.Add(new XElement("id", entity.Id.ToString()));
                    feedTempalteEle.Add(new XElement("name", entity.TemplateName));
                    feedTempalteEle.Add(new XElement("body", entity.Body));
                    feedTempalteEle.Add(new XElement("title", entity.Title));
                    feedTempalteEle.Add(new XElement("type", entity.DefaultTypeValue.ToString()));
                    feedTempalteEle.Add(new XElement("templateIcon", entity.TemplateIconName));

                    root.Add(feedTempalteEle);
                }
            }

            root.Save(exportFeedXmlFileName);

            _view.WriteLine("生成 EzDeskFeedTemplates.xml 成功");
            try
            {
                // 如果在开发环境下，尝试更新用于开发的文件
                CopyFileToDevEnv(exportFeedXmlFileName);
            }
            catch (Exception ex)
            {
                _view.WriteLine("复制生成的文件到开发环境出错，可能是没有CheckOut " + exportFeedXmlFileName + "  " + ex.Message);
            }
        }

        public void ExportCoreXml()
        {
            var root = new XElement("CoreInfo");
            LogEx.TRACE("MainForm - Presenter", "开始导出基本Core信息到XML");

            
            using (var db = new EzDeskDatabaseContainer(getEntityConnectionString(coreDatabaseName)))
            {
                var permissionGroupRoot = new XElement("permissionGroups");
                // 导出PermissionGroups列表
                var permissionGroups = db.GroupSet.Where(p => p.Type == 2);
                foreach (var entity in permissionGroups)
                {
                    var groupEle = new XElement("group");
                    groupEle.Add(new XElement("name", entity.Name));
                    groupEle.Add(new XElement("description", entity.Description));

                    // 导入包含的用户

                    if (entity.Memberstring == "everyone")
                    {
                        groupEle.Add(new XElement("groupUsers", "everyone"));
                    }
                    else
                    {
                        var users = getSimpleUserIdsFromMemberstring(entity.Memberstring);
                        var groupUsersEle = new XElement("users");
                        foreach (var simpleUser in users)
                        {
                            groupUsersEle.Add(new XElement("username", simpleUser.UserName));
                        }
                        groupEle.Add(new XElement("groupUsers", groupUsersEle));
                    }

                    permissionGroupRoot.Add(groupEle);
                }
                root.Add(permissionGroupRoot);

                var permissionRoot = new XElement("permissions");
                // 导出权限列表
                foreach (var entity in db.PermissionSet)
                {
                    var permissionEle = new XElement("permission");
                    permissionEle.Add(new XElement("name", entity.Name));
                    permissionEle.Add(new XElement("description", entity.Description));
                    permissionEle.Add(new XElement("defaultDeny", entity.DefaultDeny));

                    // 导入包含的组

                    var groups = db.Permission_GroupSet.Where(p => p.PermissionId == entity.Id);
                    
                    var groupsEle = new XElement("groups");
                    foreach (var permissionGroup in groups)
                    {
                        db.LoadProperty(permissionGroup, p => p.Group);
                        groupsEle.Add(new XElement("goups", permissionGroup.Group.Name));
                    }
                    permissionEle.Add(groupsEle);

                    permissionRoot.Add(permissionEle);
                }
                root.Add(permissionRoot);
            }
            

            root.Save(exportCoreInfoXmlFileName);
            _view.WriteLine("生成 EzDeskCoreInfo 成功");
            try
            {
                // 如果在开发环境下，尝试更新用于开发的文件
                CopyFileToDevEnv(exportCoreInfoXmlFileName);
            }
            catch (Exception ex)
            {
                _view.WriteLine("复制生成的文件到开发环境出错，可能是没有CheckOut " + exportCoreInfoXmlFileName + "  " + ex.Message);
            }

        }

        private List<SimpleUser> getSimpleUserIdsFromMemberstring(string memberstring)
        {
            if (memberstring == "everyone")
            {
                return _allUsersDic.Select(p => p.Value).ToList();
            }

            var userList = new List<SimpleUser>();
            var userIdArray = memberstring.Split(',');
            foreach (var userId in userIdArray)
            {
                if (!string.IsNullOrEmpty(userId))
                {
                    userList.Add(_allUsersDic[Guid.Parse(userId)]);
                }
            }
            return userList;
        }

        public void ImportFeedTemplates()
        {
            importFeedsTemplate(exportFeedXmlFileName);
        }

        public void ImportAppFunctions()
        {
            importAppFunctions(exportAppFunctionXmlFileName);
        }

        public void ImportCoreInfos()
        {
            importCoreInfos(exportCoreInfoXmlFileName);
        }

        

        public void InitializeAll()
        {
            // 恢复到初始化数据

            // 1. 更新数据库架构
            //refreshAllAvailableDatabaseSchema();
            // 2. 清空数据

            // 3. 写入程序初始数据

            throw new NotImplementedException();
        }






    }
}
